import React, { useState, useRef, useEffect, useImperativeHandle } from 'react';
import request from '@/utils/request';
import styles from './index.less';
import { isVideo, isImg, uid } from '@/utils';
import { useAliyunUpload, useAliyunUploadProps } from '../AliyunVideoUpload';
import classNames from 'classnames';
import { usePlvUpload, usePlvUploadProps } from '../PlvVideoUpload';
import md5 from 'crypto-js/md5';
import { throttle } from 'lodash';
import useAliyunoss from '@/hooks/useAliyunoss';
import message from '@/models/message';
import storage from '@/utils/storage';

export interface InnterUploadProps {
  action?: string;
  name?: string;
  data?: (file) => Record<string, any> | Record<string, any>;
  fileList?: any[];
  className?: string;
  onChange?: (fileList: any[], file?: any) => void;
  onSuccess?: (fileList: any[], file) => void;

  beforeUpload?: (file, fileList) => Promise<boolean>;
  onStartUpload?: () => any;
  onAfterUpload?: () => any;
  multiple?: boolean;
  /**
   * 视频传到哪个服务器
   */
  videoUploadto?: 'normal' | 'AliyunVideo' | 'Plv';
  /**
   * 图片传到哪个服务器
   */
  imgUploadto?: 'normal' | 'AliyunOSS' | 'AliyunVideo';
  getAliyunAuth?: useAliyunUploadProps['getAliyunAuth'];
  refreshAliyunAuth?: useAliyunUploadProps['refreshAliyunAuth'];
  getPlvAuth?: usePlvUploadProps['getPlvAuth'];
  refreshPlvAuth?: usePlvUploadProps['refreshPlvAuth'];
  aliyunVideoRegion?: string;
  aliyunVideoUserId?: string;
  children?: any;
  disabled?: boolean;
  max?: number;
}

export interface InnterUploadForwardRefProps {
  stopFile: (file) => boolean;
  removeFile: (file) => void;
  resumeFile: (file) => void;
  openSelect: () => void;
}

const Index = React.forwardRef<InnterUploadForwardRefProps, InnterUploadProps>(
  (
    {
      action,
      name = 'file',
      data = {},
      fileList: propsFilelist = [],
      className,
      children,
      videoUploadto = 'normal',
      imgUploadto = 'normal',
      multiple = true,
      beforeUpload,
      onStartUpload,
      onAfterUpload,
      onSuccess,
      onChange,
      getAliyunAuth,
      refreshAliyunAuth,
      getPlvAuth,
      refreshPlvAuth,
      disabled,
      aliyunVideoRegion = 'cn-shanghai',
      aliyunVideoUserId = '241647822948555848',
      max = 99,
    },
    ref,
  ) => {
    useEffect(() => {
      return () => {};
    }, []);
    const fileListRef = useRef<any>([...propsFilelist]);

    // 这边同步下propslist解决拖动排序的时候顺序不一致的问题，后面影响其他上传有问题再说
    useEffect(() => {
      fileListRef.current = [...propsFilelist];
    }, [propsFilelist]);
    const isTriggerAfterUpload = useRef(false);
    const handleChange = (fileList, file?) => {
      console.log(fileList, '1');
      onChange?.([...fileList], file);
      !isTriggerAfterUpload.current && onAfterUpload?.();
      isTriggerAfterUpload.current = true;
    };

    const throttleHandleChange = useRef(
      throttle((fileList) => handleChange(fileList), 2000),
    ).current;
    const OssData = useAliyunoss({ autoFetch: imgUploadto === 'AliyunOSS' });
    // 阿里云点播上传
    const { AliyunUploaderRef } = useAliyunUpload({
      region: aliyunVideoRegion,
      userId: aliyunVideoUserId,
      getAliyunAuth,
      refreshAliyunAuth,
      onChange: (_, file) => {
        const index = fileListRef.current?.findIndex((item) => item.uid === file.uid);

        if (index >= 0) {
          const newFileList = [...fileListRef.current];
          newFileList[index] = file;
          handleChange(newFileList, file);
        }
      },
      onSuccess: (file) => {
        if (file?.response?.videoId) {
          file.videoId = file?.response?.videoId;
        }
        onSuccess?.([...fileListRef.current], file);
      },
    });

    // 保利威云点播上传
    // https://help.polyv.net/index.html#/vod/upload_js/web_upload_sdk
    const { PlvUploaderRef } = usePlvUpload({
      getPlvAuth,
      refreshPlvAuth,
      onChange: (_, file) => {
        const index = fileListRef.current?.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          const newFileList = [...fileListRef.current];
          newFileList[index] = file;
          handleChange(newFileList, file);
        } else {
          const newFileList = [...fileListRef.current, file];
          handleChange(newFileList, file);
        }
      },
      onSuccess: (file) => {
        onSuccess?.([...fileListRef.current], file);
      },
    });

    // 同步fileListRef
    useEffect(() => {
      if (Array.isArray(propsFilelist)) {
        console.log(propsFilelist);
        // console.log(propsFilelist, 'useEffect')
        // setFlieList(propsFilelist)
        // fileListRef.current = propsFilelist;
      }
    }, []);

    const handleNormalUploadProgress = (file, e) => {
      file.percent = ((e.loaded / e.total) * 100).toFixed(0);
      handleChange(fileListRef.current, file);
      // throttleHandleChange(fileListRef.current);
    };

    const handleNormalUploadSuccess = (file, response) => {
      file.status = 'done';
      file.response = response;
      if (response?.data?.aid) {
        file.aid = response.data.aid;
      }

      handleChange(fileListRef.current, file);
      onSuccess?.([...fileListRef.current], file);
    };
    const handleNormalUploadFail = (file) => {
      file.status = 'error';
      handleChange(fileListRef.current, file);
    };

    // 图片文件上传aliyunoss
    const uploadAliyunOss = async (file) => {
      const formData = new FormData();
      const payload = typeof data === 'function' ? (data as any)?.() : data;
      if (payload) {
        for (let key in payload) {
          formData.append(key, payload[key] as any);
        }
      }
      const suffix = file.name.slice(file.name.lastIndexOf('.'));
      const filename = Date.now() + suffix;
      file.key = OssData.dir + filename;
      formData.append('key', file.key);
      formData.append('OSSAccessKeyId', OssData.accessId!);
      formData.append('policy', OssData.policy);
      formData.append('Signature', OssData.signature!);
      formData.append('file', file);
      const response = await request.postForm<any, any>(OssData.host!, formData, {
        onUploadProgress: (e) => handleNormalUploadProgress(file, e),
      });

      if (response === '') {
        file.ossUrl = OssData.host + '/' + file.key;
        handleNormalUploadSuccess(file, response);
      } else {
        handleNormalUploadFail(file);
      }

      // .then(response => {

      //   if (response?.success) {
      //     handleNormalUploadSuccess(file, response)
      //   }
      //   else {
      //     handleNormalUploadFail(file)
      //   }
      // }, () => {

      //   handleNormalUploadFail(file)
      // })
    };
    // 其他文件上传
    const uploadNormal = (file) => {
      const formData = new FormData();
      const payload = typeof data === 'function' ? (data as any)?.() : data;
      if (payload) {
        for (let key in payload) {
          formData.append(key, payload[key] as any);
        }
      }
      formData.append(name, file);
      if (!action) {
        throw new Error('action 缺少');
      }
      request
        .postForm<any, any>(action, formData, {
          onUploadProgress: (e) => handleNormalUploadProgress(file, e),
        })
        .then(
          (response) => {
            if (response?.success) {
              handleNormalUploadSuccess(file, response);
            } else {
              handleNormalUploadFail(file);
            }
          },
          () => {
            handleNormalUploadFail(file);
          },
        );
    };

    // 分流上传地址
    const shuntFile = async (file) => {
      file.uid = md5(file.name).toString().toUpperCase() + Date.now();
      const flag = await beforeUpload?.(file, fileListRef.current);
      if (flag === false) {
        return;
      }

      file.status = 'uploading';
      onStartUpload?.();

      /**
       * 视频走阿里云
       */
      if (
        (videoUploadto === 'AliyunVideo' && isVideo(file.name)) ||
        (imgUploadto === 'AliyunVideo' && isImg(file.name))
      ) {
        AliyunUploaderRef.current.addFile(file, null, null, null, '{"Vod":{}}');
        AliyunUploaderRef.current.startUpload();
      } else if (videoUploadto === 'Plv' && isVideo(file.name)) {
        /**
         * 视频走保利威
         */
        if (!PlvUploaderRef.current.addFile(file)) {
          return false;
        }
      } else if (imgUploadto === 'AliyunOSS') {
        uploadAliyunOss(file);
      }
      // 其他走正常api
      else {
        uploadNormal(file);
      }
      return file;
    };

    const onSelectFile = async (e) => {
      const files = e.target.files;
      const length = fileListRef.current.length + files.length;
      if (length > max) return;
      const arr: any[] = [];
      if (files.length <= 0) return;
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const item = await shuntFile(file);
        if (!item) {
          break;
        } else {
          fileListRef.current = [...fileListRef.current, item];
        }
      }
      // fileListRef.current = [...fileListRef.current, ...arr];
      handleChange(fileListRef.current);
      e.target.value = '';
      // (inputRef.current as any).value = ''
    };
    const stopFile = (file) => {
      if (videoUploadto === 'AliyunVideo') {
        const list = AliyunUploaderRef.current?.listFiles() || [];
        const index = list.findIndex((item) => item.file.uid === file.uid);
        if (index >= 0) {
          AliyunUploaderRef.current?.cancelFile(index);
          list[index].status = 'stop';
          handleChange([...fileListRef.current]);
          return true;
        }
        return false;
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          PlvUploaderRef.current?.stopFile(list[index]?.uploadManager?.id);
          list[index].status = 'stop';
          handleChange(list);
          return true;
        }
        return false;
      }
      return false;
    };
    const resumeFile = (file) => {
      if (videoUploadto === 'AliyunVideo') {
        const list = AliyunUploaderRef.current?.listFiles() || [];
        console.log(list);

        const index = list.findIndex((item) => item.file.uid === file.uid);

        if (index >= 0) {
          list[index].status = 'uploading';
          handleChange([...fileListRef.current]);
          AliyunUploaderRef.current?.resumeFile(index);
          AliyunUploaderRef.current?.startUpload();
          return true;
        }
        return false;
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          PlvUploaderRef.current?.resumeFile(list[index]?.uploadManager?.id);
          list[index].status = 'uploading';
          handleChange(list);
          return true;
        }
        return false;
      }
      return false;
    };
    const removeFile = (file) => {
      const index = fileListRef.current.findIndex((item) => item.uid === file.uid);

      if (videoUploadto === 'AliyunVideo') {
        const list = AliyunUploaderRef.current?.listFiles() || [];

        const index = list.findIndex((item) => item.file.uid === file.uid);

        if (index >= 0) {
          AliyunUploaderRef.current?.stopUpload();
          AliyunUploaderRef.current?.cancelFile(index);
          AliyunUploaderRef.current?.deleteFile(index);
          AliyunUploaderRef.current?.startUpload();
        }
      }
      if (videoUploadto === 'Plv') {
        const list = [...fileListRef.current];
        const index = list.findIndex((item) => item.uid === file.uid);
        if (index >= 0) {
          // 上传成功手动清除本地保利威缓存，解决同一文件读取本地存储的，导致UploadID错误
          // if (list[index]?.uploadManager?.id) {
          //   storage.remove(`hw_${list[index]?.uploadManager?.id}`)
          // }
          PlvUploaderRef.current?.removeFile(list[index]?.uploadManager?.id);
        }
      }
      if (index >= 0) {
        const newFileList = [...fileListRef.current];
        newFileList.splice(index, 1);
        fileListRef.current = newFileList;
        handleChange(newFileList);
      }
    };

    const openSelect = () => {
      inputRef.current?.click?.();
    };
    /**
     * 供父组件调用
     */
    useImperativeHandle(ref, () => ({
      stopFile,
      resumeFile,
      removeFile,
      openSelect,
    }));

    const inputRef = useRef<HTMLInputElement>(null);
    return (
      <div className={classNames(styles.innerUpload, className)}>
        <div className={styles.uploadWrapper}>
          <input
            className={classNames(styles.input, 'inner-upload-input')}
            ref={inputRef}
            title=""
            disabled={disabled}
            type="file"
            onChange={onSelectFile}
            multiple={multiple}
          />
          {children}
        </div>
      </div>
    );
  },
);

export default Index;
